package com.flex.showdoc4j.executor;

import com.flex.core.enums.SdkCommitType;
import com.flex.showdoc4j.config.Configuration;
import com.flex.showdoc4j.executor.interfaces.ClientExecutor;
import com.flex.showdoc4j.executor.interfaces.Render;
import com.flex.showdoc4j.generator.*;
import com.flex.showdoc4j.generator.commit.CommitSdk;
import com.flex.showdoc4j.generator.commit.GitCommitSdk;
import com.flex.showdoc4j.generator.commit.LocalCommitSdk;
import com.flex.showdoc4j.generator.commit.SshCommit;
import com.flex.showdoc4j.model.*;
import com.flex.showdoc4j.template.TemplateFactory;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author ganlt
 * @since 2019/06/26 17:02 <br>
 */
public class DocRender implements Render {

    @Override
    public void render(Configuration configuration) {
        List<Wrapper> wrappers = configuration.getWrappers();
        ClientExecutor executor = configuration.getClientExecutor();
        TemplateFactory templateFactory = configuration.getTemplateFactory();
        ConfigModel configModel = configuration.getConfigModel();
        for (Wrapper wrapper : wrappers) {
            renderOnce(executor, wrapper, templateFactory, configModel);
        }

        if (configuration.getConfigModel().isGeneratorSdk()) {
            generatorSdk(configuration, configuration.getWrappers());
        }
    }

    /**
     * 生成文档
     * @param configuration
     * @param wrappers
     */
    public void generatorSdk(Configuration configuration,List<Wrapper> wrappers){
        GeneratorSdkConfig generatorSdkConfig = configuration.getConfigModel().getGeneratorSdkConfig();
        GeneratorSdk generatorSdk = null;
        switch (generatorSdkConfig.getType()) {
            case js:
                generatorSdk = new JsGeneratorSdk();
                break;
            case android:
                generatorSdk = new AndroidGeneratorSdk();
                break;
            case ios:
                generatorSdk = new IosGeneratorSdk();
                break;
            default:
                throw new RuntimeException("生成未知类型"+generatorSdkConfig.getType()+"，请确认");
        }
        CommitSdk commitSdk = null;
        SdkCommitType sdkCommitType = generatorSdkConfig.getSdkCommitType();
        switch (sdkCommitType) {
            case git:
                commitSdk = new GitCommitSdk();
                break;
            case ssh:
                commitSdk = new SshCommit();
                break;
            case local:
                commitSdk = new LocalCommitSdk();
                break;
            default:
                throw new RuntimeException("创建提交类型失败"+sdkCommitType+"，请确认");
        }

        List<SdkFile> sdkFileList = new ArrayList<>();
        for (Wrapper wrapper : wrappers) {
            SdkFile sdkFile = generatorSdk.generatorSdk(generatorSdkConfig, configuration.getTemplateFactory(), wrapper);
            sdkFileList.add(sdkFile);
        }

        commitSdk.commit(generatorSdkConfig, sdkFileList);

    }



    /**
     * 执行单词渲染
     *
     * @param executor
     * @param wrapper
     * @param templateFactory
     */
    private void renderOnce(ClientExecutor executor, Wrapper wrapper, TemplateFactory templateFactory, ConfigModel configModel) {

        String result = executor.executor(wrapper);
        wrapper.getDocModel().setResult(result);

        Map<String, Object> bindMap = new HashMap<>();
        bindMap.put("doc", wrapper.getDocModel());
        bindMap.put("params", wrapper.paramModelList());
        bindMap.put("requestParamsJsonStr", wrapper.getRequestParamJsonStr());
        bindMap.put("returnJsonStr", wrapper.getRetrunJsonStr());
        bindMap.put("url", wrapper.getUrl());
        bindMap.put("returnPrams", wrapper.getReturnParamMap());
        List<ReturnChildVariableModel> childVariableModelList = new ArrayList<>();
        childs(wrapper.getReturnParamMap(), childVariableModelList);
        bindMap.put("childParams", childVariableModelList);

        String templateName = configModel.getTemplateName();
        String saveDir = configModel.getSaveDir();
        String renderStr = templateFactory.getTemplate().fileTemplateRender(templateName, bindMap);
        writerTo(renderStr, wrapper.getDocModel(), saveDir);
        writerJsonData(wrapper.getConfiguration().getConfigModel().isCreateJsonData(), saveDir + "/json/" + wrapper.getPatternUrl(), wrapper.getRetrunJsonStr());
    }

    private void childs(List<ReturnVariableModel> returnVariableModels, List<ReturnChildVariableModel> childs) {
        for (ReturnVariableModel returnVariableModel : returnVariableModels) {
            List<ReturnVariableModel> childModel = returnVariableModel.getChildModel();
            if (childModel != null) {
                ReturnChildVariableModel returnChildVariableModel = new ReturnChildVariableModel();
                returnChildVariableModel.setName(returnVariableModel.getDesc() + "[" + returnVariableModel.getName() + "]");
                returnChildVariableModel.setChildModel(childModel);
                childs.add(returnChildVariableModel);
                childs(childModel, childs);
            }
        }

    }

    private void writerTo(String templateStr, DocModel docModel, String filePath) {
        File file = new File(filePath + File.separator + docModel.getTitle() + ".md");
        try {
            if (!file.getParentFile().exists()) {
                FileUtils.forceMkdir(file.getParentFile());
            }
            FileUtils.write(file, templateStr, "utf8");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 写入data数据
     */
    private void writerJsonData(boolean isWriter, String path, String jsonData) {
        if (!isWriter) {
            return;
        }
        File file = new File(path + ".json");
        try {
            if (!file.getParentFile().exists()) {
                FileUtils.forceMkdir(file.getParentFile());
            }
            FileUtils.write(file, jsonData, "utf8");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


}
